package com.easipass.unifiedconfig.unic;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.easipass.unifiedconfig.NotFoundException;
import com.easipass.unifiedconfig.Parameter;
import com.easipass.unifiedconfig.ParametersTraverser;
import com.easipass.unifiedconfig.UCI;
import com.easipass.unifiedconfig.NotFoundException.Part;
import com.easipass.unifiedconfig.core.Authentication;

/**
 * 
 * @version $Id$
 * @author itea
 * @date 2010-1-19
 */
public class DomainRepo {

	protected final String domain;

	protected Map<String, AccountRepo> accountIdx = new TreeMap<String, AccountRepo>();
	
	public DomainRepo(String domain) {
		this.domain = domain;
	}
	
	public Parameter getParameter(UCI uci) throws NotFoundException{
		if(!uci.matchesDomain(domain))
			throw new NotFoundException(Part.DOMAIN, uci);
		AccountRepo ar = accountIdx.get(uci.getAccount());
		if(ar == null)
			throw new NotFoundException(Part.ACCOUNT, uci);
		return ar.getParameter(uci);
	}
	
	public void setParameter(Parameter p) throws NotFoundException {
		UCI uci = p.getUci();
		if(!uci.matchesDomain(domain))
			throw new NotFoundException(Part.DOMAIN, uci);
		AccountRepo ar = accountIdx.get(uci.getAccount());
		if(ar == null)
			ar = createAccountRepo(uci.getAccount());
		ar.setParameter(p);
	}
	
	public void removeParameter(UCI uci) throws NotFoundException {
		if(!uci.matchesDomain(domain))
			throw new NotFoundException(Part.DOMAIN, uci);
		AccountRepo ar = accountIdx.get(uci.getAccount());
		if(ar == null)
			throw new NotFoundException(Part.ACCOUNT, uci);
		else
			ar.removeParameter(uci);
	}
	
	public boolean containsParameter(UCI uci) {
		if(!uci.matchesDomain(domain))
			return false;
		AccountRepo ar = accountIdx.get(uci.getAccount());
		if(ar == null)
			return false;
		else
			return ar.containsParameter(uci);
	}
	
	public void traverseParameters(Authentication a, UCI range, ParametersTraverser traverser) {
		for(AccountRepo ar : accountIdx.values())
			ar.traverseParameters(a, range, traverser);
	}
	
	public AccountRepo getAccountRepo(String account) {
		return accountIdx.get(account);
	}
	
	public synchronized AccountRepo createAccountRepo(String account) {
		AccountRepo ar = accountIdx.get(account);
		if(ar == null) {
			ar = new AccountRepo(account);
			accountIdx.put(account, ar);
		}
		return ar;
	}
	
	public void removeAccountRepo(String account) {
		accountIdx.remove(account);
	}
	public List<UCI> listParameters(UCI range) {
		if(!range.matchesDomain(domain))
			return Collections.emptyList();
		List<UCI> ucis = new LinkedList<UCI>();
		for(AccountRepo ar : accountIdx.values())
			ucis.addAll(ar.listParameters(range));
		return ucis;
	}
	
	public String getDomain() {
		return domain;
	}
	
}
